﻿//using Microsoft.SqlServer.ConnectionInfo;        //in Microsoft.SqlServer.ConnectionInfo.dll

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Sdk.Sfc;    //in Microsoft.SqlServer.Management.Sdk.Sfc.dll
using Microsoft.SqlServer.Management.Smo;

//using Microsoft.SqlServer.Smo;                   //in Microsoft.SqlServer.Smo.dll
//using Microsoft.SqlServer.SmoExtended;           //in Microsoft.SqlServer.SmoExtended.dll          

namespace PRO_DOCS.DocumentManagementSystem.Petrolium.WIN.BackAndRestore
{
    public static class BackUp
    {
        public static bool BackupDatabase(string serverWithInstance, string dbName, string backUpFile, bool isTape = false)
        {
            try
            {
                var con = new ServerConnection(@serverWithInstance);
                var server = new Server(con);
                var source = new Backup { Action = BackupActionType.Database, Database = dbName };
                var destination = new BackupDeviceItem(backUpFile, isTape ? DeviceType.Tape : DeviceType.File);
                source.Devices.Add(destination);
                source.SqlBackup(server);
                con.Disconnect();
                return true;
            }
            catch (Exception ex)
            {
                Back.Backup.WriteToEventLog(ex.ToString());
                DevExpress.XtraEditors.XtraMessageBox.Show(ex.ToString());
                return true;
            }
        }

        public static bool RestoreDatabase(string serverWithInstance, string dbName, string backUpFile, bool isTape)
        {
            try
            {
                var con = new ServerConnection(@serverWithInstance);
                var server = new Server(con);
                var destination = new Restore { Action = RestoreActionType.Database, Database = dbName };
                var source = new BackupDeviceItem(backUpFile, isTape ? DeviceType.Tape : DeviceType.File);
                destination.Devices.Add(source);
                destination.ReplaceDatabase = true;

                destination.RelocateFiles.Add(new RelocateFile(dbName,
                                                               Path.Combine(server.InstallDataDirectory, "DATA",
                                                                            dbName + ".mdf")));
                destination.RelocateFiles.Add(new RelocateFile(dbName + "_Log",
                                                               Path.Combine(server.InstallDataDirectory, "DATA",
                                                                            dbName + "_Log.ldf")));

                //server.
                destination.SqlRestore(server);
                return true;
            }
            catch (Exception ex)
            {
                Back.Backup.WriteToEventLog(ex.ToString());
                DevExpress.XtraEditors.XtraMessageBox.Show(ex.ToString());
                return false;
            }
        }

        public static bool Restore(string serverWithInstance, string dbName, string backUpFile, string connString, bool isTape)
        {
            try
            {
                var scon = new ServerConnection(@serverWithInstance);
                var server = new Server(scon);

                string con = "Data Source = " + serverWithInstance +
                             "; Initial Catalog=master ;Integrated Security = True;";
                var res = GetFileNames(con, backUpFile);
                var connect = new SqlConnection(con);
                connect.Open();
                //-----------------------

                var cmdText = string.Format(@"RESTORE DATABASE [{0}] FROM DISK = '{1}' WITH ", dbName, backUpFile);

                var dataName = res.FirstOrDefault(a => a.Key.ToLower() == "d").Value;
                var logName = res.FirstOrDefault(a => a.Key.ToLower() == "l").Value;

                if (dataName != null && logName != null)
                {
                    cmdText += string.Format(@"MOVE '{0}' TO '{1}' ,", dataName,
                        @Path.Combine(server.InstallDataDirectory, "DATA", dbName + ".mdf"));
                    cmdText += string.Format(@"MOVE '{0}' TO '{1}' ", logName,
                        @Path.Combine(server.InstallDataDirectory, "DATA", dbName + "_Log.ldf"));
                }
                else
                {
                    if (dataName != null)
                    {
                        cmdText += string.Format(@"MOVE '{0}' TO '{1}'", dataName,
                        @Path.Combine(server.InstallDataDirectory, "DATA", dbName + ".mdf"));
                    }
                    else if (logName != null)
                    {
                        cmdText += string.Format(@"MOVE '{0}' TO '{1}' ", logName,
                                          @Path.Combine(server.InstallDataDirectory, "DATA", dbName + "_Log.ldf"));
                    }
                }

                //Excute SQL----------------
                SqlCommand command;
                command = new SqlCommand("use master", connect);
                command.ExecuteNonQuery();
                command = new SqlCommand(@cmdText, connect);
                command.ExecuteNonQuery();
                //------------------------
                connect.Close();
                return true;
            }
            catch (Exception ex)
            {
                Back.Backup.WriteToEventLog(ex.ToString());
                return false;
            }
        }

        private static List<KeyValuePair<string, string>> GetFileNames(string connString, string backFilePath)
        {
            try
            {
                var res = new List<KeyValuePair<string, string>>();
                var conn = new SqlConnection(connString);
                conn.Open();
                var cmd = new SqlCommand(string.Format("RESTORE FILELISTONLY FROM DISK='{0}'", backFilePath), conn);
                var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                while (reader.Read())
                {
                    res.Add(
                        new KeyValuePair<string, string>(reader["Type"].ToString(), reader["LogicalName"].ToString()));
                }
                reader.Close();
                conn.Close();
                return res;
            }
            catch (Exception ex)
            {
                Back.Backup.WriteToEventLog(ex.ToString());
                return null;
            }
        }
    }
}
